package com.x.bff.app.service.social;

import com.x.bff.app.configure.AppConfig;
import com.x.bff.app.model.vo.social.CustomerResumeFeedbackReqVO;
import com.x.bff.app.model.vo.social.CustomerResumeSearchReqVO;
import com.x.bff.app.service.common.RedisKeyService;
import com.x.core.web.page.PageDomain;
import com.x.core.web.page.PageList;
import com.x.provider.api.common.enums.ItemTypeEnum;
import com.x.provider.api.customer.enums.CustomerResourceOperBizScene;
import com.x.provider.api.customer.model.dto.customer.CustomerResourceOperReqDTO;
import com.x.provider.api.customer.model.dto.customer.CustomerResumeDTO;
import com.x.provider.api.customer.model.dto.customer.CustomerResumeSearchReqDTO;
import com.x.provider.api.customer.service.CustomerRpcService;
import com.x.provider.api.general.enums.ItemToggleRelationEnum;
import com.x.provider.api.general.enums.ItemToggleRelationTypeEnum;
import com.x.provider.api.general.model.dto.cms.ItemToggleRelationListReqDTO;
import com.x.provider.api.general.model.dto.cms.ItemToggleRelationSaveReqDTO;
import com.x.provider.api.general.service.CmsRpcService;
import com.x.provider.api.statistic.service.StatisticTotalRpcService;
import com.x.redis.domain.LongTypeTuple;
import com.x.redis.service.RedisService;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SocialServiceImpl implements SocialService{

    private static final Integer RECOMMEND_LIST_MAX_SIZE = 1000;
    private static final Integer RECOMMEND_LIST_BUILD_MAX_COUNT = 3;

    private final CustomerRpcService customerRpcService;
    private final AppConfig appConfig;
    private final StatisticTotalRpcService statisticTotalRpcService;
    private final CmsRpcService cmsRpcService;
    private final RedisService redisService;
    private final RedisKeyService redisKeyService;

    public SocialServiceImpl(CustomerRpcService customerRpcService,
                             AppConfig appConfig,
                             StatisticTotalRpcService statisticTotalRpcService,
                             CmsRpcService cmsRpcService,
                             RedisService redisService,
                             RedisKeyService redisKeyService){
        this.customerRpcService = customerRpcService;
        this.appConfig = appConfig;
        this.statisticTotalRpcService = statisticTotalRpcService;
        this.cmsRpcService = cmsRpcService;
        this.redisService = redisService;
        this.redisKeyService = redisKeyService;
    }

    @Override
    public PageList<LongTypeTuple> sliderList(CustomerResumeSearchReqVO reqVO) {
        buildRecommendList(reqVO);
        List<LongTypeTuple>  result = redisService.reverseRangeByScoreLong(redisKeyService.getCustomerResumeRecommendListKey(reqVO.getCustomerId(), reqVO.getGender()),
                reqVO.getPageDomain().getCursor(), reqVO.getPageDomain().getPageSize()).stream().collect(Collectors.toList());
        return new PageList<>(result, reqVO.getPageDomain().getPageSize(), reqVO.getPageDomain().getCursor() + 1);
    }

    private void buildRecommendList(CustomerResumeSearchReqVO reqVO) {
        String recommendListKey = redisKeyService.getCustomerResumeRecommendListKey(reqVO.getCustomerId(), reqVO.getGender());
        if (reqVO.getPageDomain().getCursor() == 0 && !redisService.hasKey(recommendListKey)){
            int i = 0;
            PageDomain pageDomain = new PageDomain();
            pageDomain.setPageSize(RECOMMEND_LIST_MAX_SIZE);
            pageDomain.setCursor(0);
            Set<Long> recommendCustomerIdList = new LinkedHashSet<>(RECOMMEND_LIST_BUILD_MAX_COUNT * 2);
            Set<Long> originCustomerIdList = new LinkedHashSet<>(RECOMMEND_LIST_BUILD_MAX_COUNT * 2);
            while (i ++ < RECOMMEND_LIST_BUILD_MAX_COUNT){
                PageList<CustomerResumeDTO> customerResumeList = customerRpcService.searchCustomerResume(CustomerResumeSearchReqDTO.builder().gender(reqVO.getGender())
                        .pageDomain(pageDomain).build()).getData();
                Set<Long> candidateCustomerIdSet = customerResumeList.getList().stream().map(item -> item.getCustomerId()).collect(Collectors.toSet());
                candidateCustomerIdSet.remove(reqVO.getCustomerId());
                originCustomerIdList.addAll(candidateCustomerIdSet);
                if (candidateCustomerIdSet.size() <= 0){
                    break;
                }
                Set<Long> unStarCandidateCustomerIdList = cmsRpcService.listItemToggleRelation(ItemToggleRelationListReqDTO.builder().fromItemId(reqVO.getCustomerId()).fromItemType(ItemTypeEnum.CUSTOMER.getValue())
                        .toItemType(ItemTypeEnum.CUSTOMER.getValue()).toItemIdList(new ArrayList<>(candidateCustomerIdSet)).relationType(ItemToggleRelationTypeEnum.STAR.getValue())
                        .relation(ItemToggleRelationEnum.FALSE_RELATION.getValue()).build()).getData().getList().stream().map(item -> item.getToItemId()).collect(Collectors.toSet());

                candidateCustomerIdSet.removeAll(unStarCandidateCustomerIdList);
                recommendCustomerIdList.addAll(candidateCustomerIdSet);
                if (recommendCustomerIdList.size() >= RECOMMEND_LIST_MAX_SIZE || customerResumeList.getList().size() < RECOMMEND_LIST_MAX_SIZE){
                    break;
                }
            }
//            if (recommendCustomerIdList.size() < RECOMMEND_LIST_MAX_SIZE){
//                originCustomerIdList.removeAll(recommendCustomerIdList);
//                recommendCustomerIdList.addAll(originCustomerIdList);
//            }
            Set<DefaultTypedTuple> recommendList = new LinkedHashSet<>(recommendCustomerIdList.size());
            int score = 0;
            for (Long customerId: recommendCustomerIdList) {
                recommendList.add(new DefaultTypedTuple(customerId, (double)score));
                score ++;
            }
            if (recommendList.isEmpty()){
                return;
            }
            redisService.zaddDefaultType(redisKeyService.getCustomerResumeRecommendListKey(reqVO.getCustomerId(), reqVO.getGender()), recommendList);
            redisService.expire(recommendListKey, Duration.ofSeconds(10));
        }
    }

    @Override
    public void readResume(CustomerResumeFeedbackReqVO reqVO) {
        if (reqVO.getStar() != null) {
            cmsRpcService.toggleRelation(ItemToggleRelationSaveReqDTO.builder().fromItemId(reqVO.getSessionCustomerId()).fromItemType(ItemTypeEnum.CUSTOMER.getValue())
                    .relation(ItemToggleRelationEnum.valueOf(reqVO.getStar()).getValue()).toItemId(reqVO.getCustomerId())
                    .toItemType(ItemTypeEnum.CUSTOMER.getValue()).relationType(ItemToggleRelationTypeEnum.STAR.getValue())
                    .build());
        }
//        return customerRpcService.operateCustomerResource(CustomerResourceOperReqDTO.builder().count(-1L).customerId(reqVO.getSessionCustomerId())
//                .resourceId(CustomerResourceOperBizScene.CustomerResourceDescBizSceneEnum.DESC_RESUME_READ_COUNT_4_READ_ONE.getId()).build()).getData();
    }
}
